<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Clipping</title>
<link rel="stylesheet" href="/cfg/format.css" type="text/css">
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="keywords" content="Java, Java2D, tutorial, clipping, programming, GUI, multiplatform">
<meta name="description" content="In this part of the Java 2D tutorial, we cover clipping.">
<meta name="language" content="en">
<meta name="author" content="Jan Bodnar">
<meta name="distribution" content="global">

<script type="text/javascript" src="/lib/jquery.js"></script>
<script type="text/javascript" src="/lib/common.js"></script>

</head>

<body>


<div class="container">

<div id="wide_ad" class="ltow">
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* 160x600, August 2011 */
google_ad_slot = "2484182563";
google_ad_width = 160;
google_ad_height = 600;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>

<div class="content">

<a href="/" title="Home">Home</a>&nbsp;
<a href="..">Contents</a>


<h1>Clipping</h1>



<p>
In this part of the Java 2D tutorial, we will talk about clipping.
</p>

<div class="center">
<script type="text/javascript"><!--
google_ad_client = "ca-pub-9706709751191532";
/* top_horizontal */
google_ad_slot = "3327173442";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>


<h2>Clipping</h2>

<p>
Clipping is restricting of drawing to a certain area. This is done for 
efficiency reasons and to create various effects. 
</p>

<p>
In the following example we will be clipping an image.
</p>

<div class="codehead">Clipping.java</div>
<pre class="code">
package com.zetcode;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;


public class Clipping extends JPanel implements ActionListener {


    private int pos_x = 8;
    private int pos_y = 8;
    private int radius = 90;

    Timer timer;
    Image image;

    private double delta[] = { 3, 3 };

    public Clipping() {

        image = new ImageIcon("bardejov.png").getImage();

        timer = new Timer(15, this);
        timer.start();
    }

    public void paint(Graphics g) {
        super.paint(g);

        Graphics2D g2d = (Graphics2D) g;

        RenderingHints rh = new RenderingHints(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);


        rh.put(RenderingHints.KEY_RENDERING,
               RenderingHints.VALUE_RENDER_QUALITY);

        g2d.setClip(new Ellipse2D.Double(pos_x, pos_y, radius, radius));

        g2d.drawImage(image,  5, 5, null);
    }

    public static void main(String[] args) {

        JFrame frame = new JFrame("Clipping");
        frame.add(new Clipping());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(400, 300);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public void actionPerformed(ActionEvent e) {

        int w = getWidth();
        int h = getHeight();

        if (pos_x &lt; 0) {
            delta[0] = Math.random() % 4 + 5;
        } else if (pos_x > w - radius) {
            delta[0] = -(Math.random() % 4 + 5);
        }

        if (pos_y &lt; 0 ) {
            delta[1] = Math.random() % 4 + 5;
        } else if (pos_y > h - radius) {
            delta[1] = -(Math.random() % 4 + 5);
        }

        pos_x += delta[0];
        pos_y += delta[1];

        repaint();
    }
}
</pre>

<p>
In this example, we will clip an image. A circle is moving on the screen and 
showing a part of the underlying image. This is as if we looked through a hole.
</p>

<pre class="explanation">
g2d.setClip(new Ellipse2D.Double(pos_x, pos_y, radius, radius));
</pre>

<p>
This is the key part of the code. Here we restrict drawing to a specific shape. 
In our case it is a circle. 
</p>

<pre class="explanation">
if (pos_x &lt; 0) {
    delta[0] = Math.random() % 4 + 5;
} else if (pos_x > w - radius) {
    delta[0] = -(Math.random() % 4 + 5);
}
</pre>

<p>
If the circle hits the left or the right side of the window, the direction of the 
circle movement changes randomly. Same for the top and bottom sides.
</p>


<img src="/img/gfx/java2d/clipping.png" alt="Clipping">
<div class="figure">Figure: Clipping</div>


<h2>Clipping shapes</h2>

<p>
In the following example, we will be clipping two shapes. A rectangle and a circle. 
</p>

<div class="codehead">ClippingShapes.java</div>
<pre class="code">
package com.zetcode;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.geom.GeneralPath;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;


public class ClippingShapes extends JPanel implements ActionListener {

    private Timer timer;

    private double rotate = 1;
    private int pos_x = 8;
    private int pos_y = 8;
    private int radius = 60;

    private double delta[] = { 1, 1 };


    public ClippingShapes() {
        timer = new Timer(10, this);
        timer.start();
    }


    public void paint(Graphics g) {

        super.paint(g);

        Graphics2D g2d = (Graphics2D)g;

        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                             RenderingHints.VALUE_ANTIALIAS_ON);

        g2d.setRenderingHint(RenderingHints.KEY_RENDERING,
                             RenderingHints.VALUE_RENDER_QUALITY);


        int w = getWidth();
        int h = getHeight();

        Rectangle rect1 = new Rectangle(0, 0, 200, 80);

        AffineTransform tx = new AffineTransform();
        tx.rotate(Math.toRadians(rotate), w / 2, h / 2);
        tx.translate(w / 2 - 100, h / 2 - 40);

        Ellipse2D circle = new Ellipse2D.Double(pos_x, pos_y, radius, radius);

        step();

        GeneralPath path = new GeneralPath();
        path.append(tx.createTransformedShape(rect1), false);

        g2d.setColor(new Color(110, 110, 110));
        g2d.clip(circle);
        g2d.clip(path);

        g2d.fill(circle);

        g2d.setClip(new Rectangle(0, 0, w, h));

        g2d.draw(circle);
        g2d.draw(path);

    }


    public void step() {
        int w = getWidth();
        int h = getHeight();

        if (pos_x &lt; 0) {
            delta[0] = 1;
        } else if (pos_x > w - radius) {
            delta[0] = -1;
        }

        if (pos_y &lt; 0) {
            delta[1] = 1;
        } else if (pos_y > h - radius) {
            delta[1] = -1;
        }

        pos_x += delta[0];
        pos_y += delta[1];
    }


    public static void main(String[] args) {
        JFrame frame = new JFrame("Clipping shapes");
        frame.add(new ClippingShapes());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(350, 300);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }


    public void actionPerformed(ActionEvent e) {
        rotate += 1;
        repaint();
    }
}
</pre>

<p>
In our example, we have a bouncing circle and a rotating rectangle. When 
these shapes overlap, the resulting area is filled
with color. 
</p>


<pre class="explanation">
Rectangle rect1 = new Rectangle(0, 0, 200, 80);

AffineTransform tx = new AffineTransform();
tx.rotate(Math.toRadians(rotate), w / 2, h / 2);
tx.translate(w / 2 - 100, h / 2 - 40);
</pre>

<p>
The rectangle is being rotated. It is always positioned in the middle of the panel. 
</p>

<pre class="explanation">
GeneralPath path = new GeneralPath();
path.append(tx.createTransformedShape(rect1), false);
</pre>

<p>
Here we get the shape of the rotated rectangle. 
</p>

<pre class="explanation">
g2d.clip(circle);
g2d.clip(path);

g2d.fill(circle)
</pre>

<p>
Here we restrict drawing to these two shapes. If they overlap, the interior of 
the resulting shape is filled with color. 
</p>

<pre class="explanation">
g2d.setClip(new Rectangle(0, 0, w, h));
</pre>

<p>
We reset the clip areas, before we draw the shapes.  
</p>

<img src="/img/gfx/java2d/clippingshapes.png" alt="Clipping Shapes">
<div class="figure">Figure: Clipping Shapes</div>


<p>
In this part of the Java 2D tutorial, we have talked about clipping.
</p>

<div class="center"> 
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* horizontal */
google_ad_slot = "1734478269";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script> 
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> 
</script> 
</div> 
<br>


<div class="botNav, center">
<span class="botNavItem"><a href="/">Home</a></span> ‡ <span class="botNavItem"><a href="..">Contents</a></span> ‡ 
<span class="botNavItem"><a href="#">Top of Page</a></span>
</div>

<div class="footer">
<div class="signature">
<a href="/">ZetCode</a> last modified September 7, 2008  <span class="copyright">&copy; 2007 - 2013 Jan Bodnar</span>
</div>
</div>

</div> <!-- content -->

</div> <!-- container -->

</body>
</html>

